package copyengine.resource.file
{
	import copyengine.resource.CEResConfig;
	import copyengine.resource.dto.ResInitDTO;
	import copyengine.resource.dto.ResObjectRequestParamDTO;
	import copyengine.utils.debug.CELog;
	import copyengine.utils.tick.GlobalTick;

	import flash.events.Event;
	import flash.events.ProgressEvent;

	public class CEBasicResFile implements ICEResFile
	{
		/**
		 * define how many time will retry to load this file.
		 */
		private static const RETRY_TIME:int = 3;

		/**
		 * resFile is an unique name , use to fine the file.
		 * WARNINIG::
		 * 		it maybe not same as the file name(filename maybe add version number to avoide cache)
		 */
		protected var resFileName:String;


		/**
		 *  define the resFile size , use in loading system to calculate the speed.
		 */
		protected var resFileMaxWeight:int;

		/**
		 *define which loadQueue current file belong to
		 */
		protected var resLoadQueueName:String;

		/**
		 * define current file load state
		 * state should be one of
		 * LOAD_STATE_UNLOAD || LOAD_STATE_LOADING || LOAD_STATE_LOADED || LOAD_STATE_ERROR
		 */
		protected var resLoadState:int = CEResConfig.LOAD_STATE_UNLOAD;

		protected var reTryTime:int = RETRY_TIME;

		private var loadComplateCallBack:Function;
		private var loadProgressCallBack:Function;
		private var loadErrorCallBack:Function;

		private var currentLoadByte:Number = 0;

		/**
		 *上层函数需要监听某个特别的素材是否加载完成时候
		 * 会set一个回调函数，让加载完成后调用该函数
		 */
		private var resLoadFinishedCallBackVector:Vector.<Function>;

		public function CEBasicResFile()
		{
		}

		public function initialize(_resInitDTO:ResInitDTO):void
		{
			resLoadFinishedCallBackVector = new Vector.<Function>();
			resFileName = _resInitDTO.resUniqueName;
			resFileMaxWeight = _resInitDTO.maxFileWeight;
			resLoadQueueName = _resInitDTO.loadQueueName;
			doInitialize(_resInitDTO);
		}

		public function startLoadFile(_loadComplateCallBack:Function, _loadProgressCallBack:Function, _loadErrorCallBack:Function):void
		{
			loadComplateCallBack = _loadComplateCallBack;
			loadProgressCallBack = _loadProgressCallBack;
			loadErrorCallBack = _loadErrorCallBack;
			resLoadState = CEResConfig.LOAD_STATE_LOADING;
			doStartLoadFile();
		}

		public final function addResLoadFinishedCallBack(_callBack:Function):void
		{
			resLoadFinishedCallBackVector.push(_callBack);
		}

		public final function removeResLoadFinishedCallBack(_callBack:Function):void
		{
			//一旦load完成后就会设置resLoadFinishedCallBackVector为空
			if (resLoadFinishedCallBackVector != null)
			{
				for (var i:int = 0; i < resLoadFinishedCallBackVector.length; i++)
				{
					if (_callBack == resLoadFinishedCallBackVector[i])
					{
						resLoadFinishedCallBackVector.splice(i, 1);
						break;
					}
				}
			}
		}

		protected final function loadFileComplate():void
		{
			resLoadState = CEResConfig.LOAD_STATE_LOADED;
			loadComplateCallBack(this);
			while (resLoadFinishedCallBackVector.length > 0)
			{
				var callBack:Function = resLoadFinishedCallBackVector.pop();
				callBack && callBack();
			}
			resLoadFinishedCallBackVector = null;
		}

		protected final function loadFileOnProgress(e:ProgressEvent):void
		{
			currentLoadByte = e.bytesLoaded;
			loadProgressCallBack(this);
		}

		protected final function loadFileOnError(e:Event):void
		{
			if (reTryTime > 0)
			{
				reTryTime--;
				CELog.warn("CEBasicResFile :: start reload file  " + fileName + "  ");
				reload();
			}
			else
			{
				CELog.err("CEBasicResFile :: can't load file  " + fileName + "  ");
				resLoadState = CEResConfig.LOAD_STATE_ERROR;
				loadErrorCallBack(this);
			}
		}

		/**
		 * reload current file.
		 * WARNINIG::
		 * 		child class should relase the loader complated at releaseLoader() function
		 * 		and start an new loader at doStartLoadFile() function.
		 */
		private function reload():void
		{
			releaseLoader();
			doStartLoadFile();
		}

		public final function get maxWeight():int
		{
			return resFileMaxWeight;
		}

		public final function get loadState():int
		{
			return resLoadState;
		}

		public final function get fileName():String
		{
			return resFileName;
		}

		public final function get loadQueueName():String
		{
			return resLoadQueueName;
		}


		//==================
		//==Overrideable Function
		//==================
		protected function doInitialize(_resInitDTO:ResInitDTO):void
		{
		}


		protected function doStartLoadFile():void
		{
		}

		/**
		 * call this function when load file complate or got error during loading
		 */
		protected function releaseLoader():void
		{
		}

		public function getObject(_dto:ResObjectRequestParamDTO):Object
		{
			return null;
		}

		public function get currentWeight():int
		{
			return currentLoadByte;
		}

		public function dispose():void
		{

		}

	}
}
